#ifndef ASM_THREAD_H
#define ASM_THREAD_H

#include <utils/types.h>
#include <utils/const.h>
#include <utils/pagesize.h>
#include <asm/memory.h>

#define KERNEL_DS       UL(-1)
#define USER_DS         ((UL(1) << MAX_USER_VA_BITS) - 1)

#define DEFAULT_MAP_WINDOW_64	(UL(1) << VA_BITS)
#define TASK_SIZE_64		(UL(1) << vabits_user)

#define DEFAULT_MAP_WINDOW	DEFAULT_MAP_WINDOW_64
#define TASK_SIZE		TASK_SIZE_64

#define STACK_TOP_MAX		DEFAULT_MAP_WINDOW_64
#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(DEFAULT_MAP_WINDOW / 4))

#define STACK_TOP		STACK_TOP_MAX

#define TIF_SIGPENDING      0
#define TIF_NEED_RESCHED	1
#define TIF_FOREIGN_FPSTATE	2	/* CPU's FP state is not current's */
#define TIF_FSCHECK         3   /* Check FS is USER_DS on return */
#define TIF_NEED_STOPED     4
#define TIF_POLLING_NRFLAG  5
#define TIF_SVE			    23	/* Scalable Vector Extension in use */
#define TIF_SVE_VL_INHERIT	24	/* Inherit sve_vl_onexec across exec */

#define _TIF_SIGPENDING		  (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED	  (1 << TIF_NEED_RESCHED)
#define _TIF_FOREIGN_FPSTATE  (1 << TIF_FOREIGN_FPSTATE)
#define _TIF_FSCHECK		  (1 << TIF_FSCHECK)
#define _TIF_NEED_STOPED      (1 << TIF_NEED_STOPED)
#define _TIF_POLLING_NRFLAG	  (1 << TIF_POLLING_NRFLAG)
#define _TIF_SVE              (1 << TIF_SVE)

#define _TIF_WORK_MASK		(_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                             _TIF_FOREIGN_FPSTATE | _TIF_FSCHECK | _TIF_NEED_STOPED)
#define _TIF_WORK_RESCHED   (_TIF_NEED_RESCHED | _TIF_NEED_STOPED)

#ifndef __ASSEMBLY__

typedef unsigned long mm_segment_t;

/*
 * low level task data that entry.S needs immediate access to.
 */
struct thread_info {
    unsigned long       flags;      /* low level flags */
    mm_segment_t        addr_limit; /* address limit */
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
	u64			ttbr0;		/* saved TTBR0_EL1 */
#endif
    union {
        u64     preempt_count;  /* 0 => preemptible, < 0 ==> bug */
        struct {
#ifdef CONFIG_CPU_BIG_ENDIAN
            u32	need_resched;
            u32	count;
#else
            u32	count;
            u32	need_resched;
#endif
        } preempt;
    };
};

#define thread_saved_pc(tsk)	\
	((unsigned long)(tsk->thread.cpu_context.pc))
#define thread_saved_sp(tsk)	\
	((unsigned long)(tsk->thread.cpu_context.sp))
#define thread_saved_fp(tsk)	\
	((unsigned long)(tsk->thread.cpu_context.fp))

#define INIT_THREAD_INFO(tsk)		\
{									\
    .flags		= _TIF_FOREIGN_FPSTATE,				\
    .addr_limit	= KERNEL_DS,		\
    .preempt_count = INIT_PREEMPT_COUNT,    \
}

static inline void init_user_thread_info(struct thread_info *thread)
{
    thread->flags = 0;
    thread->addr_limit = USER_DS;
    thread->preempt_count = 0;
}

static inline void init_idle_thread_info(struct thread_info *thread)
{
    thread->flags = _TIF_FOREIGN_FPSTATE;
    thread->addr_limit = KERNEL_DS;
    thread->preempt_count = 0;
}

#endif /* !__ASSEMBLY__ */
#endif /* !ASM_THREAD_H */
